package com.visec.hdy.log;

import com.visec.hdy.hadoop.analysis.TimeAnalysisImpl;
import com.visec.hdy.hadoop.context.LogWriteContextImpl;
import com.visec.hdy.hadoop.context.TimeLogReadContextImpl;
import com.visec.hdy.hadoop.fsb.FileSystemFSB;
import com.visec.hdy.hadoop.inquiry.TimeLogInquiryImpl;
import com.visec.hdy.hadoop.standard.Analysis;
import com.visec.hdy.hadoop.standard.FSB;
import com.visec.hdy.hadoop.standard.Inquiry;
import com.visec.hdy.hadoop.standard.Storage;
import com.visec.hdy.hadoop.storage.JsonLogStorageImpl;

/**
 * 文件系统日志存储对象
 * 
 * @author hdy
 *
 * @param <V>
 */
public class FileSystemLog<V> implements Log<V> {
	private static final long DEFAULT_FILE_SIZE = 20l;
	private FSB fsb;
	private Storage<String, V> storage;
	private Analysis<String, V, V> analysis;
	private Inquiry<String, V> inquiry;
	private String path;

	/**
	 * 
	 * @param folder
	 *            标识，用于确定日志存放目录
	 * @param key
	 *            日志对象的时间字段名称，字段格式为2018-01-12 12:55:30,或者类型为Date
	 * @param folder
	 *            存放日志的根目录，没有设置则存放在项目运行目录下
	 */
	public FileSystemLog(String folder, String key, String path) {
		this.fsb = new FileSystemFSB();
		this.path = path;
		this.storage = new JsonLogStorageImpl<>(this.fsb);
		this.analysis = new TimeAnalysisImpl<>(key);
		this.storage.setContext(new LogWriteContextImpl<>(getAbstractPath(folder), DEFAULT_FILE_SIZE));
		this.storage.open();
		this.inquiry = new TimeLogInquiryImpl<>(fsb);
		this.inquiry.setContext(new TimeLogReadContextImpl(getAbstractPath(folder), DEFAULT_FILE_SIZE));
	}

	protected String getAbstractPath(String path) {
		if (this.path == null)
			return path;
		return this.path + "/" + path;
	}

	public void setAnalysis(Analysis<String, V, V> analysis) {
		this.analysis = analysis;
	}

	/**
	 * 保存对象
	 */
	@Override
	public void save(V o) {
		this.storage.store(this.analysis.analyze(o));
		this.storage.flush();
	}

	/**
	 * 查询数据
	 * 
	 * @param start
	 *            开始时间，数据为时间戳，即为new Date().getTime()获取的时间戳
	 * @param end
	 *            结束时间
	 */
	@Override
	public Find<V> find(long start, long end) {
		inquiry.query(String.valueOf(start), String.valueOf(end));
		return new Find<>(inquiry);
	}

	@Override
	public void close() {
		this.inquiry.clear();
		this.storage.close();
		this.fsb.close();
	}
}
